package gr.uoa.di.thanos.botcraft.game;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import javax.imageio.ImageIO;

import org.lwjgl.BufferUtils;
import org.lwjgl.util.Renderable;

import java.util.logging.Level;
import java.util.logging.Logger;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;

/**
 * This enumeration represents terrain types.
 * @author thanos.papapetrou@gmail.com
 *
 */
public enum Terrain implements Renderable {
	ASH("/terrains/ash.png"),
	DIRT("/terrains/dirt.png"),
	GRASS("/terrains/grass.png"),
	ICE("/terrains/ice.png"),
	LAVA("/terrains/lava.png"),
	MUD("/terrains/mud.png"),
	ROCK("/terrains/rock.png"),
	SAND("/terrains/sand.png"),
	WATER("/terrains/water.png");
	
	private static final Logger LOGGER = Logger.getLogger(Terrain.class.getName());
	
	private static IntBuffer textures = null;
	
	private final String resource;
		
	public static void initialize() {
		textures = BufferUtils.createIntBuffer(Terrain.values().length);
		glGenTextures(textures);
		for (Terrain terrain : Terrain.values()) {
			glBindTexture(GL_TEXTURE_2D, textures.get(terrain.ordinal()));
			try {
				final BufferedImage image = ImageIO.read(Terrain.class.getResource(terrain.resource));
				final ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 3);
				for (int i = 0; i < image.getHeight(); i++) {
					for (int j = 0; j < image.getWidth(); j++) {
						final int argb = image.getRGB(j, i);
						buffer.put(i * image.getWidth() + j, Integer.valueOf((argb >>> 16) & 0xff).byteValue()).put(i * image.getWidth() + j + 1, Integer.valueOf((argb >>> 8) & 0xff).byteValue()).put(i * image.getWidth() + j + 2, Integer.valueOf(argb & 0xff).byteValue());
					}
				}
				gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image.getWidth(), image.getHeight(), GL_RGB, GL_UNSIGNED_BYTE, buffer);
			} catch (final IOException e) {
				LOGGER.log(Level.WARNING, "Error loading file " + terrain.resource + " as texture for " + Terrain.class.getName() + "." + terrain.name());
			}
		}
	}
	
	public static void dispose() {
		glDeleteTextures(textures);
	}
	
	@Override
	public void render() {
		glBindTexture(GL_TEXTURE_2D, textures.get(ordinal()));
	}
	
	private Terrain(final String resource) {
		this.resource = resource;
	}
}
